package cn.sylinx.horm.proxy.mapper.parse;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import cn.sylinx.horm.core.DynamicClient;
import cn.sylinx.horm.core.datasource.dynamic.DynamicDatasourceProvider;
import cn.sylinx.horm.exception.HORMException;
import cn.sylinx.horm.util.StrKit;
import cn.sylinx.horm.util.Tuple;

public enum NamespaceContainer {

    ;

    private static final Map<String, Namespace> container = new HashMap<>();

    public static void register(Namespace namespace) {
        container.put(namespace.getId(), namespace);
    }

    public static Namespace get(String id) {
        return container.get(id);
    }

    public static Namespace get(Class<?> mapperClass) {
        return get(mapperClass.getName());
    }

    /**
     * 
     * @param mapperClass
     * @param methodName
     * @return Tuple -->> [0] : Namespace, [1] : SqlItem, [2] : truelyDatasource
     */
    public static Tuple getMapper(Class<?> mapperClass, String methodName) {

        Namespace ns = NamespaceContainer.get(mapperClass);
        if (ns == null) {
            throw new HORMException("invalid mapper class or unregistered");
        }

        Map<String, SqlItem> sqlItems = ns.getSqlItems();
        if (sqlItems == null) {
            throw new HORMException("invalid xml mapper");
        }

        SqlItem sqlItem = sqlItems.get(methodName);
        if (sqlItem == null) {
            throw new HORMException("sqlId " + methodName + " not found");
        }

        String truelyDatasource = ns.isDynamic() ? DynamicDatasourceProvider.create().getDatasource()
                : (StrKit.isBlank(sqlItem.getDatasource())
                        ? (StrKit.isBlank(ns.getDatasource()) ? DynamicClient.DEFAULT_DS_NAME : ns.getDatasource())
                        : sqlItem.getDatasource());

        return Tuple.apply(ns, sqlItem, truelyDatasource);

    }

    public static List<Class<?>> getAllMapperClass() {
        List<Class<?>> maperClass = new ArrayList<>();
        Set<Map.Entry<String, Namespace>> namespaces = container.entrySet();
        namespaces.forEach(entry -> maperClass.add(entry.getValue().getMapperClass()));
        return maperClass;
    }
}
